/*
 * FaceCat图形通讯框架
 * 著作权编号:2015SR229355+2020SR0266727
 * 上海卷卷猫信息技术有限公司
 */

#include "stdafx.h"
#include "FCGridCell.h"

namespace FaceCat{
    FCGridCellStyle::FCGridCellStyle(){
        m_align = FCHorizontalAlign_Inherit;
        m_autoEllipsis = false;
        m_backColor = FCColor_None;
        m_font = 0;
        m_textColor = FCColor_None;
    }
    
    FCGridCellStyle::~FCGridCellStyle(){
        if(m_font){
            delete m_font;
            m_font = 0;
        }
    }
    
    FCHorizontalAlign FCGridCellStyle::getAlign(){
        return m_align;
    }
    
    void FCGridCellStyle::setAlign(FCHorizontalAlign value){
        m_align = value;
    }
    
    bool FCGridCellStyle::autoEllipsis(){
        return m_autoEllipsis;
    }
    
    void FCGridCellStyle::setAutoEllipsis(bool value){
        m_autoEllipsis = value;
    }
    
    Long FCGridCellStyle::getBackColor(){
        return m_backColor;
    }
    
    void FCGridCellStyle::setBackColor(Long value){
        m_backColor = value;
    }
    
    FCFont* FCGridCellStyle::getFont(){
        return m_font;
    }
    
    void FCGridCellStyle::setFont(FCFont *value){
        if(value){
            if(!m_font){
                m_font = new FCFont();
            }
            m_font->copy(value);
        }
        else{
            if(m_font){
                delete m_font;
                m_font = 0;
            }
        }
    }
    
    Long FCGridCellStyle::getTextColor(){
        return m_textColor;
    }
    
    void FCGridCellStyle::setTextColor(Long value){
        m_textColor = value;
    }
    
    void FCGridCellStyle::copy(FCGridCellStyle *style){
        setAutoEllipsis(style->autoEllipsis());
        setBackColor(style->getBackColor());
        setFont(style->getFont());
        setTextColor(style->getTextColor());
        setAlign(style->getAlign());
    }
    
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    
    FCGridCell::FCGridCell(){
        m_allowEdit = false;
        m_colSpan = 1;
        m_column = 0;
        m_grid = 0;
        m_row = 0;
        m_rowSpan = 1;
        m_style = 0;
        m_tag = 0;
    }
    
    FCGridCell::~FCGridCell(){
        m_column = 0;
        m_grid = 0;
        m_row = 0;
        if(m_style){
            delete m_style;
            m_style = 0;
        }
        m_tag = 0;
    }
    
    bool FCGridCell::allowEdit(){
        return m_allowEdit;
    }
    
    void FCGridCell::setAllowEdit(bool allowEdit){
        m_allowEdit = allowEdit;
    }
    
    int FCGridCell::getColSpan(){
        return m_colSpan;
    }
    
    void FCGridCell::setColSpan(int colSpan){
        m_colSpan = colSpan;
    }
    
    FCGridColumn* FCGridCell::getColumn(){
        return m_column;
    }
    
    void FCGridCell::setColumn(FCGridColumn *column){
        m_column = column;
    }
    
    FCGrid* FCGridCell::getGrid(){
        return m_grid;
    }
    
    void FCGridCell::setGrid(FCGrid *grid){
        m_grid = grid;
    }
    
    String FCGridCell::getName(){
        return m_name;
    }
    
    void FCGridCell::setName(const String& name){
        m_name = name;
    }
    
    FCGridRow* FCGridCell::getRow(){
        return m_row;
    }
    
    void FCGridCell::setRow(FCGridRow *row){
        m_row = row;
    }
    
    int FCGridCell::getRowSpan(){
        return m_rowSpan;
    }
    
    void FCGridCell::setRowSpan(int rowSpan){
        m_rowSpan = rowSpan;
    }
    
    FCGridCellStyle* FCGridCell::getStyle(){
        return m_style;
    }
    
    void FCGridCell::setStyle(FCGridCellStyle *style){
        if(style){
            if(!m_style){
                m_style = new FCGridCellStyle;
            }
            m_style->copy(style);
        }
        else{
            if(m_style){
                delete m_style;
                m_style = 0;
            }
        }
    }
    
    Object FCGridCell::getTag(){
        return m_tag;
    }
    
    void FCGridCell::setTag(Object tag){
        m_tag = tag;
    }
    
    String FCGridCell::getText(){
        return getString();
    }
    
    void FCGridCell::setText(const String& text){
        setString(text);
    }
    
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    int FCGridCell::compareTo(FCGridCell *cell){
        return 0;
    }
    
    bool FCGridCell::getBool(){
        return false;
    }
    
    double FCGridCell::getDouble(){
        return 0;
    }
    
    float FCGridCell::getFloat(){
        return 0;
    }
    
    int FCGridCell::getInt(){
        return 0;
    }
    
    Long FCGridCell::getLong(){
        return 0;
    }
    
    String FCGridCell::getPaintText(){
        return getText();
    }
    
    void FCGridCell::getAttribute(const String& name, String *value, String *type){
        if (name == L"align"){
            *type = L"enum:FCHorizontalAlign";
            FCGridCellStyle *style = getStyle();
            if (style){
                *value = FCTran::horizontalAlignToStr(style->getAlign());
            }
        }
        else if(name == L"allowedit"){
            *type = L"bool";
            *value = FCTran::boolToStr(allowEdit());
        }
        else if (name == L"autoellipsis"){
            *type = L"bool";
            FCGridCellStyle *style = getStyle();
            if (style){
                *value = FCTran::boolToStr(style->autoEllipsis());
            }
        }
        else if(name == L"backcolor"){
            *type = L"color";
            FCGridCellStyle *style = getStyle();
            if (style){
                *value = FCTran::colorToStr(style->getBackColor());
            }
        }
        else if(name == L"colspan"){
            *type = L"int";
            *value = FCTran::intToStr(getColSpan());
        }
        else if(name == L"font"){
            *type = L"font";
            FCGridCellStyle *style = getStyle();
            if (style && style->getFont()){
                *value = FCTran::fontToStr(style->getFont());
            }
        }
        else if(name == L"textcolor"){
            *type = L"color";
            FCGridCellStyle *style = getStyle();
            if (style){
                *value = FCTran::colorToStr(style->getTextColor());
            }
        }
        else if(name == L"name"){
            *type = L"text";
            *value = getName();
        }
        else if (name == L"rowspan"){
            *type = L"int";
            *value = FCTran::intToStr(getRowSpan());
        }
        else if(name == L"text"){
            *type = L"text";
            *value = getText();
        }
        else{
            *type = L"undefined";
            *value = L"";
        }
    }
    
    ArrayList<String> FCGridCell::getAttributeNames(){
        ArrayList<String> attributeNames;
        attributeNames.add(L"Align");
        attributeNames.add(L"AllowEdit");
        attributeNames.add(L"AutoEllipsis");
        attributeNames.add(L"BackColor");
        attributeNames.add(L"ColSpan");
        attributeNames.add(L"Font");
        attributeNames.add(L"Name");
        attributeNames.add(L"RowSpan");
        attributeNames.add(L"Text");
        attributeNames.add(L"TextColor");
        return attributeNames;
    }
    
    String FCGridCell::getString(){
        return L"";
    }
    
    void FCGridCell::onAdd(){
    }
    
    void FCGridCell::onPaint(FCPaint *paint, const FCRect& rect, const FCRect& clipRect, bool isAlternate){
        int clipW = clipRect.right - clipRect.left;
        int clipH = clipRect.bottom - clipRect.top;
        if (clipW > 0 && clipH> 0){
            if(m_grid && m_row && m_column){
                String text = getPaintText();
                bool selected = false;
                FCGridSelectionMode selectionMode = m_grid->getSelectionMode();
                if(selectionMode == FCGridSelectionMode_SelectCell){
                    ArrayList<FCGridCell*> selectedCells = m_grid->getSelectedCells();
                    int cellSize = (int)selectedCells.size();
                    for (int i = 0; i < cellSize; i++){
                        if (selectedCells.get(i) == this){
                            selected = true;
                            break;
                        }
                    }
                }
                else if (selectionMode == FCGridSelectionMode_SelectFullColumn){
                    ArrayList<FCGridColumn*> selectedColumns = m_grid->getSelectedColumns();
                    int selectedColumnsSize = (int)selectedColumns.size();
                    for(int i = 0; i < selectedColumnsSize; i++){
                        if(selectedColumns.get(i) == m_column){
                            selected = true;
                            break;
                        }
                    }
                }
                else if (selectionMode == FCGridSelectionMode_SelectFullRow){
                    ArrayList<FCGridRow*> selectedRows = m_grid->getSelectedRows();
                    int selectedRowsSize = (int)selectedRows.size();
                    for(int i = 0; i < selectedRowsSize; i++){
                        if(selectedRows.get(i) == m_row){
                            selected = true;
                            break;
                        }
                    }
                }
                FCFont *font = 0;
                Long backColor = FCColor_None;
                Long textColor = FCColor_None;
                bool autoEllipsis = m_grid->autoEllipsis();
                
                FCGridRowStyle *rowStyle = m_grid->getRowStyle();
               if (isAlternate){
                   FCGridRowStyle *alternateRowStyle = m_grid->getAlternateRowStyle();
                   if (alternateRowStyle){
                       rowStyle = alternateRowStyle;
                   }
               }
               if(rowStyle){
                   if(selectionMode != FCGridSelectionMode_SelectFullRow){
                       if (backColor == FCColor_None){
                           if (selected){
                               backColor = rowStyle->getSelectedBackColor();
                           }
                           else if (m_row == m_grid->getHoveredRow()){
                               backColor = rowStyle->getHoveredBackColor();
                           }
                           else{
                               backColor = rowStyle->getBackColor();
                           }
                       }
                   }
                   if(!font){
                       font = rowStyle->getFont();
                   }
                   if (textColor == FCColor_None){
                       if (selected){
                           textColor = rowStyle->getSelectedTextColor();
                       }
                       else if (m_row == m_grid->getHoveredRow()){
                           textColor = rowStyle->getHoveredTextColor();
                       }
                       else{
                           textColor = rowStyle->getTextColor();
                       }
                   }
               }
                
                FCHorizontalAlign horizontalAlign = m_column->getCellAlign();
                if (m_style){
                    if (m_style->autoEllipsis()){
                        autoEllipsis = m_style->autoEllipsis();
                    }
                    if(m_style->getBackColor() != FCColor_None){
                        backColor = m_style->getBackColor();
                    }
                    if (m_style->getFont()){
                        font = m_style->getFont();
                    }
                    if(m_style->getTextColor() != FCColor_None){
                        textColor = m_style->getTextColor();
                    }
                    if (m_style->getAlign() != FCHorizontalAlign_Inherit){
                        horizontalAlign = m_style->getAlign();
                    }
                }
               
                paint->fillRect(backColor, rect);
                FCSize tSize = paint->textSize(text, font, -1);
                FCRect tRect = {0};
                tRect.left = rect.left + 1;
                tRect.top = rect.top + (clipH - tSize.cy) / 2;
                int width = rect.right - rect.left;
                if(tSize.cx < width){
                    if (horizontalAlign == FCHorizontalAlign_Center){
                        tRect.left = rect.left + (rect.right - rect.left - tSize.cx) / 2;
                    }
                    else if (horizontalAlign == FCHorizontalAlign_Right){
                        tRect.left = rect.right - tSize.cx - 2;
                    }
                }
                tRect.right = tRect.left + tSize.cx;
                tRect.bottom = tRect.top + tSize.cy;
                if(autoEllipsis && (tRect.right > clipRect.right || tRect.bottom > clipRect.bottom)){
                    if (tRect.right > clipRect.right) {
                        tRect.right = clipRect.right;
                    }
                    if (tRect.bottom > clipRect.bottom) {
                        tRect.bottom = clipRect.bottom;
                    }
                    paint->drawTextAutoEllipsis(text, textColor, font, tRect);
                }
                else{
                    paint->drawText(text, textColor, font, tRect, -1);
                }
            }
        }
    }
    
    void FCGridCell::onRemove(){
    }
    
    void FCGridCell::setBool(bool value){
    }
    
    void FCGridCell::setDouble(double value){
    }
    
    void FCGridCell::setFloat(float value){
    }
    
    void FCGridCell::setInt(int value){
    }
    
    void FCGridCell::setLong(Long value){
    }
    
    void FCGridCell::setAttribute(const String& name, const String& value){
        if (name == L"align"){
            if (!m_style){
                m_style = new FCGridCellStyle;
            }
            m_style->setAlign(FCTran::strToHorizontalAlign(value));
        }
        else if(name == L"allowedit"){
            setAllowEdit(FCTran::strToBool(value));
        }
        else if (name == L"autoellipsis"){
            if (!m_style){
                m_style = new FCGridCellStyle;
            }
            m_style->setAutoEllipsis(FCTran::strToBool(value));
        }
        else if(name == L"backcolor"){
            if (!m_style){
                m_style = new FCGridCellStyle;
            }
            m_style->setBackColor(FCTran::strToColor(value));
        }
        else if (name == L"colspan"){
            setColSpan(FCTran::strToInt(value));
        }
        else if(name == L"font"){
            if (!m_style){
                m_style = new FCGridCellStyle;
            }
            FCFont nFont = FCTran::strToFont(value);
            m_style->setFont(&nFont);
        }
        else if(name == L"textcolor"){
            if (!m_style){
                m_style = new FCGridCellStyle;
            }
            m_style->setTextColor(FCTran::strToColor(value));
        }
        else if(name == L"name"){
            setName(value);
        }
        else if (name == L"rowspan"){
            setRowSpan(FCTran::strToInt(value));
        }
        else if(name == L"text"){
            setText(value);
        }
    }
    
    void FCGridCell::setString(const String& value){
    }
    
    FCGridViewCell::FCGridViewCell(){
        m_view = 0;
    }
    
    FCGridViewCell::~FCGridViewCell(){
        if(m_view){
            delete m_view;
            m_view = 0;
        }
    }
    
    FCView* FCGridViewCell::getView(){
        return m_view;
    }
    
    void FCGridViewCell::setView(FCView *view){
        m_view = view;
    }
    
    String FCGridViewCell::getPaintText(){
        return L"";
    }
    
    String FCGridViewCell::getString(){
        if(m_view){
            return m_view->getText();
        }
        else{
            return L"";
        }
    }

    void FCGridViewCell::callTouchEvent(String eventName, Object sender, FCTouchInfo touchInfo, Object invoke){
        if (sender == m_view) {
            if (eventName == L"ontouchdown") {
                onViewTouchDown(touchInfo);
            } else if (eventName == L"ontouchmove") {
                onViewTouchMove(touchInfo);
            } else if (eventName == L"ontouchup") {
                onViewTouchUp(touchInfo);
            } else if (eventName == L"ontouchwheel") {
                onViewTouchWheel(touchInfo);
            }
        }
    }
    
    void FCGridViewCell::onAdd(){
        FCGrid *grid = getGrid();
        if (m_view && grid){
            grid->addView(m_view);
            m_view->addEvent((FCTouchEventCallBack*)this, L"ontouchdown", this);
            m_view->addEvent((FCTouchEventCallBack*)this, L"ontouchmove", this);
            m_view->addEvent((FCTouchEventCallBack*)this, L"ontouchup", this);
            m_view->addEvent((FCTouchEventCallBack*)this, L"ontouchwheel", this);
        }
    }
    
    void FCGridViewCell::onViewTouchDown(FCTouchInfo touchInfo){
        FCGrid *grid = getGrid();
        if(grid && m_view){
            FCTouchInfo newTouchInfo = touchInfo;
            newTouchInfo.m_firstPoint = grid->pointToView(m_view->pointToNative(newTouchInfo.m_firstPoint));
            newTouchInfo.m_secondPoint = grid->pointToView(m_view->pointToNative(newTouchInfo.m_secondPoint));
            grid->onTouchDown(newTouchInfo);
        }
    }
    
    void FCGridViewCell::onViewTouchMove(FCTouchInfo touchInfo){
        FCGrid *grid = getGrid();
        if(grid && m_view){
            FCTouchInfo newTouchInfo = touchInfo;
            newTouchInfo.m_firstPoint = grid->pointToView(m_view->pointToNative(newTouchInfo.m_firstPoint));
            newTouchInfo.m_secondPoint = grid->pointToView(m_view->pointToNative(newTouchInfo.m_secondPoint));
            grid->onTouchMove(newTouchInfo);
        }
    }
    
    void FCGridViewCell::onViewTouchUp(FCTouchInfo touchInfo){
        FCGrid *grid = getGrid();
        if(grid && m_view){
            FCTouchInfo newTouchInfo = touchInfo;
            newTouchInfo.m_firstPoint = grid->pointToView(m_view->pointToNative(newTouchInfo.m_firstPoint));
            newTouchInfo.m_secondPoint = grid->pointToView(m_view->pointToNative(newTouchInfo.m_secondPoint));
            grid->onTouchUp(newTouchInfo);
        }
    }
    
    void FCGridViewCell::onViewTouchWheel(FCTouchInfo touchInfo){
        FCGrid *grid = getGrid();
        if(grid && m_view){
            FCTouchInfo newTouchInfo = touchInfo;
            newTouchInfo.m_firstPoint = grid->pointToView(m_view->pointToNative(newTouchInfo.m_firstPoint));
            newTouchInfo.m_secondPoint = grid->pointToView(m_view->pointToNative(newTouchInfo.m_secondPoint));
            grid->onTouchWheel(newTouchInfo);
        }
    }
    
    void FCGridViewCell::onPaint(FCPaint *paint, const FCRect& rect, const FCRect& clipRect, bool isAlternate){
        FCGridCell::onPaint(paint, rect, clipRect, isAlternate);
        onPaintView(paint, rect, clipRect);
    }
    
    void FCGridViewCell::onPaintView(FCPaint *paint, const FCRect& rect, const FCRect& clipRect){
        if (m_view){
            FCRect bounds = {rect.left + 1, rect.top + 1, rect.right - 1, rect.bottom - 1};
            m_view->setBounds(bounds);
            FCRect newClipRect = clipRect;
            newClipRect.left -= rect.left;
            newClipRect.top -=  rect.top;
            newClipRect.right -= rect.left;
            newClipRect.bottom -= rect.top;
            m_view->setRegion(newClipRect);
        }
    }

    void FCGridCell::onScaling(double scaleFactorX, double scaleFactorY) {
        if (m_style) {
            if (m_style->m_font) {
                m_style->m_font->m_fontSize = (float)(m_style->m_font->m_fontSize * (scaleFactorX + scaleFactorY) / 2);
            }
        }
    }
    
    void FCGridViewCell::onRemove(){
        FCGrid *grid = getGrid();
        if (m_view && grid){
            m_view->removeEvent((FCTouchEventCallBack*)this, L"ontouchdown");
            m_view->removeEvent((FCTouchEventCallBack*)this, L"ontouchmove");
            m_view->removeEvent((FCTouchEventCallBack*)this, L"ontouchup");
            m_view->removeEvent((FCTouchEventCallBack*)this, L"ontouchwheel");
            grid->removeView(m_view);
        }
    }
    
    void FCGridViewCell::setString(const String& value){
        if(m_view){
            return m_view->setText(value);
        }
    }
}
